package com.hulk.dryad.persistence.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.google.common.collect.Lists;
import com.hulk.dryad.persistence.entity.ProcessInstanceModel;
import com.hulk.dryad.persistence.service.IProcessInstanceService;
import lombok.AllArgsConstructor;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.engine.RepositoryService;

import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author hulk
 * @version 1.0
 * @date 2020/12/1 10:13
 */
@AllArgsConstructor
@Service
public class ProcessInstanceServiceImpl implements IProcessInstanceService {

	private RepositoryService repositoryService;

	private ProcessRuntime processRuntime;


	@Override
	public ProcessInstanceModel startProcess(String processDefinitionKey, String instanceName, String businessKey, Map<String, Object> variables) {

		ProcessInstance pi = processRuntime.start(ProcessPayloadBuilder
				.start()
				.withProcessDefinitionKey(processDefinitionKey)
				.withName(instanceName)
				.withVariables(variables)
				.withBusinessKey(businessKey)
				.build());
		ProcessInstanceModel model = covertProcessInstanceModel(pi);
		return model;
	}


	@Override
	public IPage<ProcessInstanceModel> getProcessInstancePage(Page page, ProcessInstanceModel processInstanceModel) {

		org.activiti.api.runtime.shared.query.Page<ProcessInstance> processInstancePage = processRuntime.processInstances(Pageable.of((int) ((page.getCurrent() - 1) * page.getSize()), (int) page.getSize()));

		List<ProcessInstance> processInstances = processInstancePage.getContent();
		processInstances.sort((y, x) -> x.getStartDate().toString().compareTo(y.getStartDate().toString()));

		List<ProcessInstanceModel> processInstanceModels = Lists.newArrayList();
		for (ProcessInstance pi : processInstances) {
			ProcessInstanceModel model = covertProcessInstanceModel(pi);
			processInstanceModels.add(model);
		}
		page.setRecords(processInstanceModels);
		return page;
	}

	@Override
	public ProcessInstanceModel getInstance(String instanceId) {
		ProcessInstance pi = processRuntime.processInstance(instanceId);
		ProcessInstanceModel model = covertProcessInstanceModel(pi);
		return model;
	}

	@Override
	public ProcessInstanceModel removeInstance(String instanceId) {

		ProcessInstance pi = processRuntime.delete(ProcessPayloadBuilder
				.delete()
				.withProcessInstanceId(instanceId)
				.build()
		);
		ProcessInstanceModel model = covertProcessInstanceModel(pi);
		return model;


	}

	@Override
	public ProcessInstanceModel suspendInstance(String instanceID) {

		ProcessInstance pi = processRuntime.suspend(ProcessPayloadBuilder
				.suspend()
				.withProcessInstanceId(instanceID)
				.build()
		);
		ProcessInstanceModel model = covertProcessInstanceModel(pi);
		return model;

	}

	@Override
	public ProcessInstanceModel activeInstance(String instanceID) {
		ProcessInstance pi = processRuntime.resume(ProcessPayloadBuilder
				.resume()
				.withProcessInstanceId(instanceID)
				.build()
		);
		ProcessInstanceModel model = covertProcessInstanceModel(pi);
		return model;
	}

	@Override
	public List<VariableInstance> getVariables(String instanceID) {
		List<VariableInstance> variableInstances = processRuntime.variables(ProcessPayloadBuilder
				.variables()
				.withProcessInstanceId(instanceID)
				.build());
		return variableInstances;
	}

	private ProcessInstanceModel covertProcessInstanceModel(ProcessInstance pi) {
		ProcessInstanceModel model = new ProcessInstanceModel();
		model.setId(pi.getId());
		model.setName(pi.getName());
		model.setStatus(pi.getStatus().name());
		model.setProcessDefinitionId(pi.getProcessDefinitionId());
		model.setProcessDefinitionKey(pi.getProcessDefinitionKey());
		model.setStartDate(pi.getStartDate());
		model.setProcessDefinitionVersion(pi.getProcessDefinitionVersion());

		//因为processRuntime.processDefinition("流程部署ID")查询的结果没有部署流程与部署ID，所以用repositoryService查询
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(pi.getProcessDefinitionId())
				.singleResult();
		model.setResourceName(pd.getResourceName());
		model.setDeploymentId(pd.getDeploymentId());
		return model;
	}

}
